#include <iostream>

#include "core/EventLoopThreadPool.h"

#include "ThreadPool/TaskQueueTemplate/SingletonTemplate.h"
#include "ThreadPool/TaskQueueTemplate/QueueThreadPool.h"

#include <thread>
#include <chrono>
#include <mutex>

#include <boost/asio.hpp>

#define THREAD_SUM 1
#define NUM_SUM 100

std::mutex g_mutex;
std::mutex g_mutex_print;
std::vector<long> g_vec;
void Insert(long a)
{
    std::lock_guard<std::mutex> lg(g_mutex);
    g_vec.push_back(a);
}

size_t VectorSize()
{
    return g_vec.size();
}

void VectorClear()
{
    std::lock_guard<std::mutex> lg(g_mutex);
    g_vec.clear();
}


void produceThreadPool(int i, long sum)
{
    long start = i * sum;
    long end = start + sum;
    //std::cout << start << " " << end<< std::endl;
    while (end > start)
    {
        SingletonTemplate<QueueThreadPool>::GetInstance()->AddTask([=]() {
            //std::lock_guard<std::mutex> lg(g_mutex_print);
            //std::cout << std::this_thread::get_id() << " " << start << std::endl;
            Insert(start);
            });
        ++start;
    }

}
void produceEventThreadPool(int i, long sum)
{
    long start = i * sum;
    long end = start + sum;
    while (end > start)
    {
        SingletonTemplate<trantor::EventLoopThreadPool>::GetInstance()->getNextLoop()->runInLoop([=]() {
            //std::lock_guard<std::mutex> lg(g_mutex);
            //std::cout << std::this_thread::get_id() << " " << start << std::endl;
            Insert(start);
            });
        ++start;
    }
}

void ASIOrun(boost::asio::io_context& _io)
{
        _io.run();
        std::cout << "asio run() return\n";
}

void produceASIO(boost::asio::io_context& _io, int i, long sum)
{
    long start = i * sum;
    long end = start + sum;
    while (end > start)
    {
        _io.post([=]() {
            //std::lock_guard<std::mutex> lg(g_mutex);
            Insert(start);
            });
        ++start;
    }
    
}

int main(int args, char **argv) 
{
    int ThreadSum = THREAD_SUM;
    int NumSum = NUM_SUM; 
    std::cout << "hello " << args << std::endl;
    if (3 == args)
    {
        ThreadSum = atoi(argv[1]);
        NumSum = atoi(argv[2]);
    }
    
    std::cout << ThreadSum << " " << NumSum << std::endl;

    int all = ThreadSum * NumSum;
    SingletonTemplate<QueueThreadPool>::Instance(ThreadSum);

    SingletonTemplate<trantor::EventLoopThreadPool>::Instance(ThreadSum);
    SingletonTemplate<trantor::EventLoopThreadPool>::GetInstance()->start();

    boost::asio::io_context _io;
    boost::asio::io_context::work _worker(_io);
    std::vector<std::thread> threadsASIORun;
    for (int i = 0; i < ThreadSum; ++i) {
        threadsASIORun.emplace_back(ASIOrun, std::ref(_io));
    }

    auto start = std::chrono::high_resolution_clock::now();
    std::vector<std::thread> threadsProducePool;
    for (int i = 0; i < ThreadSum; ++i) {
        threadsProducePool.emplace_back(produceThreadPool, i,  NumSum);
    }
    while (all != VectorSize())
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }
    std::cout << "UserThreadPoolsize:" << VectorSize() << std::endl;
    auto end = std::chrono::high_resolution_clock::now();
    VectorClear();

    auto start1 = std::chrono::high_resolution_clock::now();
    std::vector<std::thread> threadsEventProducePool;
    for (int i = 0; i < ThreadSum; ++i) {
        threadsEventProducePool.emplace_back(produceEventThreadPool, i,  NumSum);
    }
    while (all != VectorSize())
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }
    std::cout << "Drogonsize:" << VectorSize() << std::endl;
    auto end1 = std::chrono::high_resolution_clock::now();
    VectorClear();

    std::cout << "ASIOsize:" << VectorSize() << std::endl;
    auto start2 = std::chrono::high_resolution_clock::now();
    std::vector<std::thread> threadsProduceASIO;
    for (int i = 0; i < ThreadSum; ++i) {
        threadsProduceASIO.emplace_back(produceASIO, std::ref(_io), i, NumSum);
    }
    while (all != VectorSize())
    {
        //std::cout << "size:" << VectorSize() << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }
    std::cout << "ASIOsize:" << VectorSize() << std::endl;
    auto end2 = std::chrono::high_resolution_clock::now();

    // 计算时间差，即运行时间
    std::chrono::duration<double> elapsed = end - start;
    std::chrono::duration<double> elapsed1 = end1 - start1;
    std::chrono::duration<double> elapsed2 = end2 - start2;

    // 输出运行时间
    std::cout << "\nUser Thread Pool Elapsed time: " << elapsed.count() << "s\n\n";
    std::cout << "\nDrogon Elapsed time: " << elapsed1.count() << "s\n\n";
    std::cout << "\nASIO Elapsed2 time: " << elapsed2.count() << "s\n\n";

    std::cout << "over\n";
    pause();
}